# MIT License
#
# Copyright (c) 2025 milkpotatoes
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

cmake_minimum_required(VERSION 3.10)

set(CMAKE_CXX_STANDARD 17)
project(StandloneNapi)

set(ARK_PATH ${ARK_ABS_REPO_PATH}/arkcompiler)

set(NAPI_PATH arkui_napi)

execute_process(
  COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/patch_and_getres.sh"
  RESULT_VARIABLE acec_napi_patch_result
  OUTPUT_VARIABLE ace_napi_patch_srcs
  ERROR_VARIABLE acec_napi_patch_error
  OUTPUT_STRIP_TRAILING_WHITESPACE
  ERROR_STRIP_TRAILING_WHITESPACE
)

string(REPLACE "\n" ";" ace_napi_srcs "${ace_napi_patch_srcs}")

set(ARK_GEN_PATH "${ARK_ABS_REPO_PATH}/out/${ARK_BUILD_ARCH}.${ARK_BUILD_TYPE}")

if(NOT HOST_ARCH STREQUAL ${ARK_BUILD_ARCH})
  if(EXISTS "${ARK_ABS_REPO_PATH}/out/${HOST_ARCH}.release")
    set(ARK_HOST_GEN_PATH "${ARK_ABS_REPO_PATH}/out/${HOST_ARCH}.release")
  elseif(EXISTS "${ARK_ABS_REPO_PATH}/out/${HOST_ARCH}.debug")
    set(ARK_HOST_GEN_PATH "${ARK_ABS_REPO_PATH}/out/${HOST_ARCH}.debug")
  else()
    message(FATAL_ERROR "Host ark toolchain path is not found.")
  endif()
else()
  set(ARK_HOST_GEN_PATH ${ARK_GEN_PATH})
  add_subdirectory(sdk)
endif()

include_directories(
  ${ARK_ABS_REPO_PATH}/third_party/bounds_checking_function/include)

aux_source_directory(src/mock ace_napi_srcs)

# 设置C工程的 CFLAGS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O1")
# 设置C++ 工程的 CXX_FLAGS
set(CMAKE_CXX_FLAGS
  "${CMAKE_CXX_FLAGS}\
    -Wextra\
    -Wformat\
    -Werror\
    -Wno-unused-parameter\
    -Wno-unused-variable\
    -Werror=attributes\
    -Wno-error=narrowing\
    -Wno-unused-value\
    -Wno-missing-braces\
    -Wno-c++11-narrowing\
    -Wno-gnu-statement-expression\
    -Wno-missing-field-initializers\
    -Wno-unused-command-line-argument\
    -Wreorder-ctor\
    -Wno-sign-compare\
    -Wno-invalid-offsetof")

if(CODE_INFO)
  add_compile_options(-g)
endif()

file(GLOB TS_MODULES "src/js/*.ts")
list(FILTER TS_MODULES EXCLUDE REGEX "\\.d\\.ts$")
set(TS_MODULE_SRC)

if(DEBUG_JS_MODULE)
  message("Non-merge abc is required")
endif()

foreach(item IN LISTS TS_MODULES)
  get_filename_component(MODULE_NAME ${item} NAME_WE)
  add_custom_target(
    ${MODULE_NAME}_bytecode
    COMMAND ${ARK_HOST_GEN_PATH}/arkcompiler/ets_frontend/es2abc --module
    ${item} --output ${CMAKE_CURRENT_BINARY_DIR}/${MODULE_NAME}.abc
    BYPRODUCTS ${MODULE_NAME}.abc
    COMMENT "build ${MODULE_NAME} file to pandafile")

  if(DEBUG_JS_MODULE)
    get_filename_component(ABC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR} ABSOLUTE)
    set(TS_MODULE_OUT_DIR ${ABC_OUT_DIR})
  else()
    add_custom_target(
      ${MODULE_NAME}_source
      COMMAND ${PROJECT_SOURCE_DIR}/tools/file2bin.py -i ${MODULE_NAME}.abc -o ${MODULE_NAME}.abc.c
      DEPENDS ${MODULE_NAME}_bytecode
      BYPRODUCTS ${MODULE_NAME}.abc.c
      COMMENT "gen bytecode of source file")

    list(APPEND TS_MODULE_SRC ${CMAKE_CURRENT_BINARY_DIR}/${MODULE_NAME}.abc.c)
  endif()
endforeach()

# libace_napi.so
add_library(ace_napi SHARED ${ace_napi_srcs})
target_link_libraries(
  ace_napi
  PRIVATE
  ${ARK_GEN_PATH}/thirdparty/libuv/libuv.so
  ${ARK_GEN_PATH}/thirdparty/icu/libhmicuuc.so
  ${ARK_GEN_PATH}/arkcompiler/ets_runtime/libark_jsruntime.so
  ${ARK_GEN_PATH}/thirdparty/bounds_checking_function/libsec_shared.so
)

target_compile_definitions(ace_napi PUBLIC LINUX_PLATFORM PREVIEW PANDA_TARGET_UNIX)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
  target_compile_definitions(ace_napi PUBLIC NDEBUG)
endif()

target_include_directories(
  ace_napi
  PRIVATE
  ${ARK_PATH}/ets_runtime
  ${ARK_PATH}/runtime_core
  ${ARK_PATH}/runtime_core/common_interfaces
  ${ARK_GEN_PATH}/arkcompiler
  ${NAPI_PATH}
  ${ARK_ABS_REPO_PATH}/third_party/icu/icu4c/source/common
  ${NAPI_PATH}/native_engine
  ${NAPI_PATH}/native_engine/impl/ark
  PUBLIC
  ${ARK_ABS_REPO_PATH}/third_party/libuv/include
  ${ARK_ABS_REPO_PATH}/third_party/node/src
  ${NAPI_PATH}/interfaces/kits
  ${NAPI_PATH}/interfaces/inner_api
)

get_property(
  ACE_NAPI_INTERFACE
  TARGET ace_napi
  PROPERTY INTERFACE_INCLUDE_DIRECTORIES)

aux_source_directory(src NAPI_RUNNER_SRCS)
aux_source_directory(src/utils NAPI_RUNNER_SRCS)
aux_source_directory(src/js_utils NAPI_RUNNER_SRCS)
add_executable(napi_runner ${NAPI_RUNNER_SRCS} ${TS_MODULE_SRC})

add_dependencies(napi_runner ace_napi)
target_compile_definitions(napi_runner PRIVATE BUILD_OUTPUT_DIR="${CMAKE_BINARY_DIR}")
if(DEBUG_JS_MODULE)
  target_compile_definitions(napi_runner PRIVATE TS_MODULE_OUT_DIR="${TS_MODULE_OUT_DIR}")
  target_compile_definitions(napi_runner PRIVATE DEBUG_JS_MODULE)
  foreach(item IN LISTS TS_MODULES)
    get_filename_component(MODULE_NAME ${item} NAME_WE)
    add_dependencies(napi_runner ${MODULE_NAME}_bytecode)
  endforeach()
else()
  foreach(item IN LISTS TS_MODULES)
    get_filename_component(MODULE_NAME ${item} NAME_WE)
    add_dependencies(napi_runner ${MODULE_NAME}_source)
  endforeach()
endif()

target_link_libraries(
  napi_runner
  PRIVATE
  ace_napi
  ${ARK_GEN_PATH}/arkcompiler/ets_runtime/libark_jsruntime.so
  ${ARK_GEN_PATH}/thirdparty/icu/libhmicuuc.so
  ${ARK_GEN_PATH}/thirdparty/libuv/libuv.so
)

if(CMAKE_SYSTEM_NAME STREQUAL "OHOS")
  set_target_properties(ace_napi PROPERTIES
    OUTPUT_NAME "ace_napi"
    PREFIX "lib"
    SUFFIX ".z.so"
  )
endif()

target_include_directories(napi_runner
  PRIVATE
  ${ACE_NAPI_INTERFACE}
  ${ARK_ABS_REPO_PATH}/third_party/icu/icu4c/source/common
  ${ARK_ABS_REPO_PATH}/arkcompiler/runtime_core/common_interfaces
  ${ARK_PATH}/ets_runtime
  ${ARK_PATH}/runtime_core
  ${ARK_PATH}/runtime_core/libpandabase
  ${ARK_PATH}/runtime_core/libpandafile
  ${ARK_PATH}/runtime_core/platforms
  ${ARK_GEN_PATH}/arkcompiler
  ${ARK_GEN_PATH}/gen/arkcompiler/runtime_core/libpandabase
  ${ARK_GEN_PATH}/gen/arkcompiler/runtime_core/libpandabase/include
  ${ARK_GEN_PATH}/gen/arkcompiler/runtime_core/libpandafile
  ${ARK_GEN_PATH}/gen/arkcompiler/runtime_core/libpandafile/include
  ${NAPI_PATH}
  ${NAPI_PATH}/native_engine/impl/ark
  src/js_utils/include
  src/utils/include
  third_party/cxxopts/include
)

if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
  target_link_libraries(ace_napi
    PRIVATE
    ${ARK_GEN_PATH}/thirdparty/icu/libhmicui18n.so
    ${ARK_GEN_PATH}/arkcompiler/ets_runtime/libark_jsoptimizer.so
  )
  target_link_libraries(napi_runner PRIVATE ${ARK_GEN_PATH}/thirdparty/icu/libhmicui18n.so)
endif()

if(NOT CMAKE_SYSTEM_NAME STREQUAL OHOS)
  add_custom_command(
    OUTPUT ${PROJECT_SOURCE_DIR}/es2abc ${PROJECT_SOURCE_DIR}/napi_runner
    COMMAND rm -f ${PROJECT_SOURCE_DIR}/napi_runner
    COMMAND ln -s ${CMAKE_CURRENT_BINARY_DIR}/napi_runner ${PROJECT_SOURCE_DIR}/napi_runner
    COMMAND rm -f ${PROJECT_SOURCE_DIR}/es2abc
    COMMAND ln -sr ${ARK_HOST_GEN_PATH}/arkcompiler/ets_frontend/es2abc ${PROJECT_SOURCE_DIR}/es2abc
    DEPENDS napi_runner
    COMMENT "make symbol for executable files")
endif()

add_custom_target(
  GenerateFiles ALL
  DEPENDS ${PROJECT_SOURCE_DIR}/es2abc)

if(EXISTS demo/CMakeLists.txt)
  add_subdirectory(demo)
endif()

add_subdirectory(tests/native)
